#include <math.h>
#include <sndfile.h>
#include <stdio.h>
#include "sekai/VoiceSampler.h"

class MyVoiceSampler : public VoiceSampler {
  virtual bool addOnePulse();
  //TODO: voice handle

 private:
  int _samplerate = 0;
  float _scaleFactor = 1.0;
  float _pitchShift = 1.0;

 public:
  MyVoiceSampler(int buffersize, std::string voicepath)
      : VoiceSampler(buffersize) {
    //FIXME: VoiceSampler::load(voice, _samplerate, voicepath);
  }
  int samplerate() { return _samplerate; }
  void setTimeScale(float factor) { _scaleFactor = factor; }
  void setPitchShift(float factor) { _pitchShift = factor; }
};

#if 0
bool MyVoiceSampler::addOnePulse() {
  float currentIndex = inputPositionSamples();
  currentIndex /= _scaleFactor;
  float currentTime = currentIndex / _samplerate;

  Pitch pmkL, pmkR;
  Pitch f0L, f0R;

  float f0_interp = 0;
  float pmk_interp = 0;

  int pmkIndex =
      findPitchMark(voice.pmkTrack, currentTime, pmkL, pmkR, &pmk_interp);
  int f0Index = findPitchMark(voice.f0Track, currentTime, f0L, f0R, &f0_interp);
  // printf("f0_interp %f\n",f0_interp);
  float input_f0 = 500;
  if (f0L.f0 > 0 && f0R.f0 > 0) {
    input_f0 = f0L.f0 * (1 - f0_interp) + f0R.f0 * f0_interp;
    // printf("input_f0: %f\n",input_f0);
  }

  if (f0Index == -1) return false;  // end of file

  float output_f0 = input_f0 * _pitchShift;

  int period = _samplerate / output_f0;

  int posL = pmkL.pos * _samplerate;
  int posR = pmkR.pos * _samplerate;

  int period2 = _samplerate / input_f0 * 2;
  float impulse_response[period2];
  float impulse_response_L[period2];
  float impulse_response_R[period2];

  // if(pmk_interp>0.5) pmk_interp=1.0; else pmk_interp=0.0;

  for (int i = 0; i < period2; i++) {
    if (i + posL < voice.input_data_length)
      impulse_response_L[i] = voice.input_data[i + posL];
    else
      impulse_response_L[i] = 0;
    if (i + posR < voice.input_data_length)
      impulse_response_R[i] = voice.input_data[i + posR];
    else
      impulse_response_R[i] = 0;

    impulse_response[i] = impulse_response_L[i] * (1 - pmk_interp) +
                          impulse_response_L[i] * pmk_interp;
  }

  VoiceSampler::hanningWindow(impulse_response, period2);

  // fractional delay is added here
  ola(impulse_response, period2, period);
  return true;
}
#endif

int main(int argc, char** argv) {
  if (argc < 3) {
    printf(
        "usage: vosamp_test input.wav output.wav [timescale] [pitchshift]\n");
    return 1;
  }
  std::string voicepath = argv[1];
  std::string outfile = argv[2];
  MyVoiceSampler vosamp(8192, voicepath);

  if (argc > 3) vosamp.setTimeScale(atof(argv[3]));
  if (argc > 4) vosamp.setPitchShift(atof(argv[4]));

  SF_INFO info = {0};
  info.samplerate = vosamp.samplerate();
  info.channels = 1;
  info.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16;

  SNDFILE* sf = sf_open(outfile.c_str(), SFM_WRITE, &info);

  while (1) {
    int size = 1024;
    int fill = size * 4;

    float buffer_out[size];
    if (vosamp.readData(buffer_out, size, fill) == false) break;
    sf_write_float(sf, buffer_out, size);
  }

  sf_close(sf);
}

// TODO: copyout, window function
